package com.core;

import java.lang.reflect.Method;

import org.json.JSONObject;

import com.core.views.IWebView;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.webkit.JavascriptInterface;

/**
 * 
 * @author 殷田
 *
 */
public class Engine
{

	private IWebView webView;
	private InterfaceManager apiManager;

	private Engine()
	{
		apiManager=new InterfaceManager();
	}

	public static Engine create( Context context )
	{
		Engine engine = new Engine();
		engine.init( context );
		return engine;
	}

	private void init( Context context )
	{
		webView = new IWebView( context );
		setConfig( webView );
		webView.setFocusableInTouchMode( true );
		webView.setFocusable( true );
	}

	private void setConfig( IWebView webView )
	{
		webView.addJavascriptInterface( new Bridge(), "bridge" );
	}

	public IWebView getWebView()
	{
		return webView;
	}

	public void execJsFuc( String methodName, String... params )
	{
		if ( methodName != null && methodName.length() > 0 )
		{
			StringBuffer buffer = new StringBuffer();
			buffer.append( "javascript:" ).append( methodName ).append( "(" );
			if ( params != null )
			{
				for ( int i = 0; i < params.length; i++ )
				{
					buffer.append( params[i] );
					if ( i < ( params.length - 1 ) )
					{
						buffer.append( "," );
					}
				}
			}
			buffer.append( ")" );
			Log.i( "Engine", buffer.toString() );
			new Executor().execFuc( buffer.toString() );
		}
	}

	public void execJsFuc( String uri )
	{
		if ( uri != null && uri.length() > 0 )
		{
			new Executor().execFuc( uri );
		}
	}
	
	public void addInterface(String name,Object api)
	{
		apiManager.put( name, api );
	}
	
	public void removeInterface(String name)
	{
		apiManager.remove( name );
	}

	public void destory()
	{
		if ( webView != null )
		{
			webView.destroy();
			webView = null;
		}
	}

	/**
	 * 原生与JS之间的沟通桥梁
	 * 
	 * @author 殷田
	 *
	 */
	public class Bridge
	{

		@JavascriptInterface
		public void exec( String apiName, String methodName, String callBackId, String param )
		{
			Executor executor = new Executor();
			try
			{
				if ( !intercept( apiName, methodName, callBackId, param ) )
				{
					Method method = null;
					Object feature = apiManager.get( apiName );
					if ( feature != null )
					{
						method = apiManager.getMethod( apiName, methodName );
					}
					if ( method == null )
					{
						String hint = ( feature == null ? "no such feature" : "no such method" );
						executor.callback( callBackId, hint, false );
					}
					else
					{
						Object[] args = new Object[] { executor, callBackId, param };
						method.invoke( feature, args );
					}
				}
			}
			catch ( Exception e )
			{
				e.printStackTrace();
				executor.callback( callBackId, e.getMessage(), false );
			}
		}
	}

	private boolean intercept( String apiName, String methodName, String id, String param )
	{
		return false;
	}

	/**
	 * 监听网页连接桥插件是否加载完成
	 * 
	 * @author 殷田
	 *
	 */
	public class PlugReady
	{
		public void OnReady( Executor executor, String callBackId, String param )
		{
			Log.i( "PlugReady", "callBackId: " + callBackId + " param: " + param );
		}
	}

	/**
	 * Js函数执行器
	 * 
	 * @author 殷田
	 *
	 */
	private class Executor implements JsExecutor
	{
		/**
		 * 直接执行 key对应的 js回调函数
		 * 
		 * @param id:回调Id
		 * @param result:返回给回调的结果
		 * @param isSuccess:函数是否执行成功
		 */
		@Override
		public void callback( String id, String result, boolean isSuccess )
		{
			try
			{
				final JSONObject object = new JSONObject();
				object.put( "key", id );
				object.put( "result", result );
				object.put( "state", isSuccess );
				execFuc( "javascript:plus.jsExecutor.exec(" + object.toString() + ")" );
			}
			catch ( Exception e )
			{
				e.printStackTrace();
			}
		}

		/**
		 * 执行JS函数
		 * 
		 * @param Uri例如javascript:alert("点击了确定")
		 */
		public void execFuc( final String Uri )
		{
			try
			{
				handler.post( new Runnable()
				{

					@Override
					public void run()
					{
						webView.loadUrl( Uri );
					}
				} );
			}
			catch ( Exception e )
			{
				e.printStackTrace();
			}
		}
	}

	private Handler handler = new Handler( Looper.getMainLooper() );
}
